package com.spark.gaea.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.spark.gaea.utils.exception.ApiException;
import com.spark.gaea.utils.exception.GaeaAuthenticationException;
import com.spark.gaea.utils.exception.GaeaRuntimeException;
import com.spark.gaea.utils.json.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public class SdkUtil {
	private HttpClient httpClient;
	private String baseUri;
	private ObjectMapper mapper;

	public SdkUtil(final String baseUri) {
		this.mapper = JsonUtil.getMapper();
		this.httpClient = HttpClients.createDefault();
		this.baseUri = baseUri;
	}

	public Object request(final HttpServletRequest request) {
		try {
			final String method = request.getMethod();
			final String uri = request.getRequestURI().replace(request.getContextPath() + "/", "");
			final String cookie = request.getHeader("Cookie");
			final Map<String, String[]> params = (Map<String, String[]>) request.getParameterMap();
			if (method.equalsIgnoreCase("POST")) {
				return this.post(uri, params, cookie);
			}
			return this.get(uri, params, cookie);
		} catch (IOException e) {
			throw new GaeaRuntimeException("远程连接出现异常", e);
		}
	}

	private Object get(final String command, final Map<String, String[]> params, final String cookie)
			throws IOException {
		RequestBuilder builder = RequestBuilder.get().setUri(this.baseUri + command);
		if (params != null) {
			for (final String key : params.keySet()) {
				for (final String value : params.get(key)) {
					builder = builder.addParameter(key, value);
				}
			}
		}
		return this.request(builder.build(), cookie);
	}

	private Object post(final String uri, final Map<String, String[]> params, final String cookie) throws IOException {
		final HttpPost httpRequest = new HttpPost(this.baseUri + uri);
		final List<NameValuePair> appParams = Lists.newArrayList();
		if (params != null) {
			for (final String key : params.keySet()) {
				for (final String value : params.get(key)) {
					appParams.add(new BasicNameValuePair(key, value));
				}
			}
		}
		final HttpEntity httpEntity = new UrlEncodedFormEntity(appParams, "UTF-8");
		httpRequest.setEntity(httpEntity);
		return this.request(httpRequest, cookie);
	}

	private Object request(final HttpUriRequest request, final String cookie) throws IOException {
		request.setHeader("Cookie", cookie);
		final HttpResponse response = this.httpClient.execute(request);
		final String responseText = EntityUtils.toString(response.getEntity());
		if (StringUtils.isNotBlank(responseText)) {
			final Object result = this.mapper.readValue(responseText, Object.class);
			if (result instanceof Map) {
				final Map map = (Map) result;
				if (map.get("errorCode") != null) {
					if (map.get("errorCode").equals(401)) {
						throw new GaeaAuthenticationException((String) map.get("errorText"));
					}
					if (map.get("errorCode").equals(432)) {
						throw new ApiException((String) map.get("errorText"));
					}
					throw new GaeaRuntimeException((String) map.get("errorText"));
				}
			}
			return result;
		}
		return null;
	}
}
